﻿unit faceUtils;
interface
uses
 Types,  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls;
var
 FFaceHandle: pointer; 
const
 ASF_DETECT_MODE_VIDEO = $00000000; //Video 模式，一般用于多帧连续检测
 ASF_DETECT_MODE_IMAGE = $FFFFFFFF; // Image 模式，一般用于静态图的单次检测
 ASF_NONE = $00000000; //无属性
 ASF_FACE_DETECT = $00000001; //此处 detect 可以是 tracking 或者 detection 两个引擎之一，具体的选择由 detect mode 确定
 ASF_FACERECOGNITION = $00000004; //人脸特征
 ASF_AGE = $00000008; //年龄
 ASF_GENDER = $00000010; //性别
 ASF_FACE3DANGLE = $00000020; //3D 角度
 ASF_LIVENESS = $00000080; //RGB 活体
 ASF_IR_LIVENESS = $00000400; //红外活体
//检测时候 Orientation 优先级别
 ASF_OP_0_ONLY = $1; // 0, 0, ...
 ASF_OP_90_ONLY = $2; // 90, 90, ...
 ASF_OP_270_ONLY = $3; // 270, 270, ...
 ASF_OP_180_ONLY = $4; // 180, 180, ...
 ASF_OP_0_HIGHER_EXT = $5; // 0, 90, 270, 180, 0, 90, 270, 180, ...
/// 当前 SDK 版本，VIDEO 模式下支持 ASF_OP_0_HIGHER_EXT 检测，IMAGE 模式不支持
 ASF_OC_0 = $1; // 0 degree
 ASF_OC_90 = $2; // 90 degree
 ASF_OC_270 = $3; // 270 degree
 ASF_OC_180 = $4; // 180 degree
 ASF_OC_30 = $5; // 30 degree
 ASF_OC_60 = $6; // 60 degree
 ASF_OC_120 = $7; // 120 degree
 ASF_OC_150 = $8; // 150 degree
 ASF_OC_210 = $9; // 210 degree
 ASF_OC_240 = $A; // 240 degree
 ASF_OC_300 = $B; // 300 degree
 ASF_OC_330 = $C; // 330 degree
 ASVL_PAF_I420 = $601;
 ASVL_PAF_RGB24_B8G8R8 = $201; // 513
 MOK = (0);
 MERR_NONE = (0);
type
 //检测模型
 ASF_DetectModel = (
  ASF_DETECT_MODEL_RGB = $1 //RGB 图像检测模型
 //预留扩展其他检测模型
 );
 //人脸比对可选的模型
 ASF_CompareModel = (
   ASF_LIFE_PHOTO = $1, //用于生活照之间的特征比对，推荐阈值 0.80
   ASF_ID_PHOTO = $2 //用于证件照或生活照与证件照之间的特征比对，推荐阈值 0.82
 );
//duDWORD，LongInt，Cardinal 三种数据 zhi 类型都一样，都是 32 位无符号 dao 整型(无符号就是没有负的，
//最小值内为 0，和之相对的有符号 32 位整型就是最常用容的 Integer)
type
 MPChar = pchar;
 Mint8 = Shortint; // -128..127 signed 8-bit
 PMint8 = ^Mint8;
 Muint8 = Byte; //0..255 unsigned 8-bit
 PMuint8 = ^Muint8;
 Mint16 = Smallint; //-32768..32767 signed 16-bit
 PMint16 = ^Mint16;
 Muint16 = WORD; //word 是 2 字节 unsigned 16-bit
 PMuint16 = ^Muint16;
 MInt32 = Longint; //-2147483648..2147483647 signed 32-bit
 PMint32 = ^MInt32;
 MUInt32 = DWORD; //Longword unsigned 32-bit
 PMuint32 = ^MUInt32;
 pMByte = ^MByte;
 MByte = Byte; //0..255 unsigned 8-bit
 MWord = WORD; //word 是 2 字节 unsigned 16-bit
 MFloat = Single; // 这里必须是 Single ,4bytes 32 位浮点数.
//不能 double;8 bytes 64 位浮点数 否则无法输出人脸比较
 pMRECT = ^MRECT;
 MRECT = record
 left: MInt32;
 top: MInt32;
 right: MInt32;
 bottom: MInt32;
 end;
 //单人脸信息
 LPASF_SingleFaceInfo = ^ASF_SingleFaceInfo;
 ASF_SingleFaceInfo = record
   faceRect: MRECT; // 人脸框信息
   faceOrient: MInt32; // 输入图像的角度，可以参考 ArcFaceCompare_OrientCode
 end;
 //多人脸信息
 LPASF_MultiFaceInfo = ^ASF_MultiFaceInfo;
 ASF_MultiFaceInfo = record
   faceRect: array of MRECT; // 人脸框数组
   faceOrient: array of MInt32; // 人脸角度数组
   faceNum: MInt32; // 检测到的人脸个数
   faceID: MInt32; //在 VIDEO 模式下有效，IMAGE 模式下为空
 end;
 LPASF_FaceFeature = ^ASF_FaceFeature;
 ASF_FaceFeature = record
   feature: pMByte; //array[0..2048] of byte; // pMuint8; // 人脸特征信息
   featureSize: MInt32; // 人脸特征信息长度
 end;
 LPASF_FaceAngle = ^ASF_FaceAngle;
 ASF_FaceAngle = record
   roll: MFloat;
   yaw: MFloat;
   pitch: MFloat;
   status: integer; //0: 正常，其他数值：出错
   num: PMuint32
 end;
 LPASF_AgeInfo = ^ASF_AgeInfo;
 ASF_AgeInfo = record
   ageArray: MInt32; // "0" 代表不确定，
   num: MInt32; // 检测的人脸个数
 end;
 //结构体
 LPASVLOFFSCREEN = ^ASVLOFFSCREEN;
 ASVLOFFSCREEN = record
   u32PixelArrayFormat: MUInt32; //BMP 格式必须为 ASVL_PAF_RGB24_B8G8R8，
   i32Width: MInt32; //图像的每行像素数
   i32Height: MInt32;
   ppu8Plane: array[0..3] of pMUInt8; //ppu8Plane 为一个批向 byte 数组的指针数组，
   //这里面会保存我们刚刚转换后的图片数据。可以传递四幅图片。
   pi32Pitch: array[0..3] of MInt32;
 end;
 LPASVLOF = ^ASVLOFFSCREEN;
 __tag_ASVL_OFFSCREEN = ASVLOFFSCREEN;
 ASF_ImageData = ASVLOFFSCREEN;
 LPASF_ImageData = ^ASVLOFFSCREEN;
 LPASF_LivenessInfo = ^ASF_LivenessInfo;
 ASF_LivenessInfo = record
 isLive: pMInt32; // [out] 判断是否真人， 0：非真人；
 // 1：真人；
 // -1：不确定；
 // -2:传入人脸数>1；
 // -3: 人脸过小
 // -4: 角度过大
 // -5: 人脸超出边界
 num: MInt32;
 end;
// 激活文件信息
 LPASF_ActiveFileInfo = ^ASF_ActiveFileInfo;
 ASF_ActiveFileInfo = record
 startTime: MPChar; //开始时间
 endTime: MPChar; //截止时间
 platform: MPChar; //平台
 sdkType: MPChar; //sdk 类型
 appId: MPChar; //APPID
 sdkKey: MPChar; //SDKKEY
 sdkVersion: MPChar; //SDK 版本号
 fileVersion: MPChar; //激活文件版本号
 end;
 //版本信息
 LPASF_VERSION = ^ASF_VERSION;
 ASF_VERSION = record
 Version: MPChar; // 版本号
 BuildDate: MPChar; // 构建日期
 CopyRight: MPChar; // Copyright
 end;
function ASFActivation(appId: PAnsiChar; sdkKey: PAnsiChar): integer; cdecl;
function ASFInitEngine(detectMode: MInt32;
 detectFaceOrientPriority: MInt32;
 detectFaceScaleVal: MInt32; //人脸在图片中所占比例，有效数值为 2-32 ;
 detectFaceMaxNum: MInt32;
 combinedMask: MInt32; pEngine: pointer): integer; cdecl;
function ASFDetectFaces(pEngine: pointer; width: MInt32; height: MInt32;
 format: MInt32; imgData: PMuint8; detectedFaces: pointer): integer; cdecl;
function ASFDetectFacesEx(pEngine: pointer;
 imgData: LPASF_ImageData; // [in] 图片数据
 detectedFaces: LPASF_MultiFaceInfo; // [out] 检测到的人脸信息
 detectModel: ASF_DetectModel = ASF_DETECT_MODEL_RGB ): integer; cdecl; // [out]
function ASFFaceFeatureExtract(pEngine: pointer; width: MInt32; height: MInt32;
 format: MInt32; imgData: PMuint8;
 faceInfo: pointer; // [in] 单张人脸位置和角度信息
 feature: pointer): integer; cdecl; // [out] 人脸特征
function ASFGetFace3DAngle(pEngine: pointer; // [in] 引擎 handle
 p3DAngleInfo: LPASF_FaceAngle): integer; cdecl; // [out] 检测到脸部 3D 角度信息
function ASFProcess_IR(hEngine: pointer; width: MInt32; height: MInt32; format: MInt32; imgData: 
PMuint8; var detectedFaces: ASF_MultiFaceInfo; combinedMask: MInt32): integer; cdecl;
function ASFFaceFeatureCompare(
 pEngine: pointer; // [in] 引擎 handle
 var feature1: ASF_FaceFeature; // [in] 待比较人脸特征 1
 var feature2: ASF_FaceFeature; // [in] 待比较人脸特征 2
 var confidenceLevel: MFloat; // [out] 比较结果，置信度数值
 compareModel: ASF_CompareModel = ASF_LIFE_PHOTO
 ): integer; cdecl;
function ASFGetAge(
 pEngine: pointer; // [in] 引擎 handle
 ageInfo: LPASF_AgeInfo // [out] 检测到的年龄信息
 ): integer; cdecl;
function ASFGetLivenessScore(
 pEngine: pointer; // [in] 引擎 handle
 livenessInfo: LPASF_LivenessInfo // [out] 检测 RGB 活体结果
 ): integer; cdecl;
function ASFGetVersion(): ASF_VERSION; cdecl;
implementation
var
 FMASK: MInt32;
 iRet: integer;
 appId, sdkKey: string;
const
 DllName = 'libarcsoft_face_engine.dll';
function ASFActivation; cdecl; external DllName;
function ASFInitEngine; cdecl; external DllName;
function ASFDetectFaces; cdecl; external DllName;
function ASFDetectFacesEx; cdecl; external DllName;
function ASFFaceFeatureExtract; cdecl; external DllName;
function ASFGetFace3DAngle; cdecl; external DllName;
function ASFProcess_IR; cdecl; external DllName;
function ASFFaceFeatureCompare; cdecl; external DllName;
function ASFGetAge; cdecl; external DllName;
function ASFGetVersion; cdecl; external DllName;
function ASFGetLivenessScore; cdecl; external DllName;
initialization
 FFaceHandle := nil;
 FMASK := ASF_FACE_DETECT
 or ASF_FACERECOGNITION
 or ASF_AGE or ASF_GENDER
 or ASF_FACE3DANGLE
 or ASF_LIVENESS or ASF_IR_LIVENESS;
 iRet := ASFActivation('app', 'key');
 iRet := ASFInitEngine(ASF_DETECT_MODE_IMAGE,
 ASF_OP_0_ONLY,32, //2-32 最小人脸
 5, FMASK, @FFACEHandle);
END.